/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package transervfx.Dato.Entidad;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Objects;
import javafx.beans.property.adapter.JavaBeanIntegerProperty;
import javafx.beans.property.adapter.JavaBeanIntegerPropertyBuilder;
import javafx.beans.property.adapter.JavaBeanProperty;
import javafx.beans.property.adapter.JavaBeanStringProperty;
import javafx.beans.property.adapter.JavaBeanStringPropertyBuilder;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import org.hibernate.validator.constraints.NotEmpty;
import org.hibernate.validator.constraints.Range;
import transervfx.Dato.Validacion.NoExisteUsuario;
import transervfx.Dato.Validacion.ValidacionesNivelBD;
import transervfx.Dato.Validacion.ValidacionesNivelLogico;

/**
 *
 * @author oscar
 */
@NamedQueries({
    @NamedQuery( name = "Usuario.findAll", query = "SELECT u FROM Usuario u"),
    @NamedQuery( name = "Usuario.count", query = "SELECT COUNT(u) FROM Usuario u "),
    @NamedQuery( name = "Usuario.findByNombre", query = "SELECT u FROM Usuario u WHERE u.nombre = :nombre"),
    @NamedQuery( name = "Usuario.findByApellido", query = "SELECT u FROM Usuario u WHERE u.apellido = :apellido"),
    @NamedQuery( name = "Usuario.findByNombreUsuario", query = "SELECT u FROM Usuario u WHERE u.nombreUsuario = :nombreUsuario"),
    @NamedQuery( name = "Usuario.findByNroDoc", query = "SELECT u FROM Usuario u WHERE u.nroDoc = :nroDoc"),
    @NamedQuery( name = "Usuario.findByNombreAndCave", query = "SELECT u FROM Usuario u WHERE (u.nombreUsuario = :nombreUsuario) AND (u.clave = :clave)"),
    @NamedQuery( name = "Usuario.findByNombreAndApellido", query = "SELECT u FROM Usuario u WHERE (u.nombre = :nombre) AND (u.apellido = :apellido)")
})
@Entity
public class Usuario implements Serializable {

    private static final long serialVersionUID = 1L;
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id;
    //un usuario tiene restricciones para la validacion, que se indican con las anotaciones
    //NotNull es una ya creada por el estandar
    //a las anotaciones se las pueden agrupar, como se indican ahi con groups
    //ej: ValidacionesNivelLogico es una interfaz q solo agrupa validaciones logicas, internamente no hace nada
    //sirve solo para agurpar
    @NotNull(message = "no puede ser nulo", groups = ValidacionesNivelLogico.class)
    @NotEmpty(message = "debe completarlo", groups = ValidacionesNivelLogico.class)
    @Size(min = 4, max = 12, message = "4 letras minimos, 12 maximo", groups = ValidacionesNivelLogico.class)
    //en este caso la validacion la hice yo, y es a nivel de BD, es decir, que cada vez q haga en la bd pordia agrupar validaciones de bd
    @NoExisteUsuario(message = "el usuario existe", groups = ValidacionesNivelBD.class)
    private String nombreUsuario;
    
    @NotNull(message = "no puede ser nulo", groups = ValidacionesNivelLogico.class)
    @NotEmpty(message = "debe completarlo", groups = ValidacionesNivelLogico.class)
    @Size(min = 4, max = 12, message = "4 letras minimos, 12 maximo", groups = ValidacionesNivelLogico.class)
    private String clave;
    
    @NotEmpty(message = "debe seleccionar uno", groups = ValidacionesNivelLogico.class)
    @Size(min = 3, max = 5, message = "seleccione uno", groups = ValidacionesNivelLogico.class)
    private String tipo;
    

    @Pattern(regexp = "^([A-Z][a-zA-Z]{1, 29})+$", message = "debe poseer entre 4 y 12 caracteres", groups = ValidacionesNivelLogico.class)
    private String nombre;
    
    @NotNull(message = "no puede ser nulo", groups = ValidacionesNivelLogico.class)
    @NotEmpty(message = "debe completarlo", groups = ValidacionesNivelLogico.class)
    @Size(min = 4, max = 12, message = "4 letras minimos, 12 maximo", groups = ValidacionesNivelLogico.class)
    private String apellido;
    
    @Range(min = 10000000, max = 99999999, message = "8 digitos como minimo y maximo", groups = ValidacionesNivelLogico.class)
    private Integer nroDoc;
    
    @NotEmpty(message = "debe seleccionar uno", groups = ValidacionesNivelLogico.class)
    @Size(min = 3, max = 5, message = "seleccione uno", groups = ValidacionesNivelLogico.class)
    private String tipoDoc;
    
    //-------------------propiedades binding
    @Transient
    private JavaBeanStringProperty PROP_NOMBREUSUARIO;
    @Transient
    private JavaBeanStringProperty PROP_CLAVE;
    @Transient
    private JavaBeanStringProperty PROP_TIPO;
    @Transient
    private JavaBeanStringProperty PROP_NOMBRE;
    @Transient
    private JavaBeanStringProperty PROP_APELLIDO;
    @Transient
    private JavaBeanIntegerProperty PROP_NRODOC;
    @Transient
    private JavaBeanStringProperty PROP_TIPODOC;
    @Transient
    private ArrayList<JavaBeanProperty> GroupBindProperties = new ArrayList<JavaBeanProperty>();

    public Usuario(String nombreUsuario, String clave) {
        this.nombreUsuario = nombreUsuario;
        this.clave = clave;
    }

    public Usuario() {
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getNombreUsuario() {
        return nombreUsuario;
    }

    public void setNombreUsuario(String nombreUsuario) {
        this.nombreUsuario = nombreUsuario;
    }

    public String getClave() {
        return clave;
    }

    public void setClave(String clave) {
        this.clave = clave;
    }

    public String getTipo() {
        return tipo;
    }

    public void setTipo(String tipo) {
        this.tipo = tipo;
    }

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public String getApellido() {
        return apellido;
    }

    public void setApellido(String apellido) {
        this.apellido = apellido;
    }

    public Integer getNroDoc() {
        return nroDoc;
    }

    public void setNroDoc(Integer nroDoc) {
        this.nroDoc = nroDoc;
    }

    public String getTipoDoc() {
        return tipoDoc;
    }

    public void setTipoDoc(String TipoDoc) {
        this.tipoDoc = TipoDoc;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 47 * hash + Objects.hashCode(this.id);
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Usuario other = (Usuario) obj;
        if (!Objects.equals(this.id, other.id)) {
            return false;
        }
        return true;
    }

    //----------------------CODIGO BINDING
    public JavaBeanStringProperty getPROP_NOMBREUSUARIO() throws NoSuchMethodException {
        if (PROP_NOMBREUSUARIO == null) {
            PROP_NOMBREUSUARIO = JavaBeanStringPropertyBuilder.create().bean(this).name("nombreUsuario").build();
            GroupBindProperties.add(PROP_NOMBREUSUARIO);
        }
        return PROP_NOMBREUSUARIO;
    }

    public JavaBeanStringProperty getPROP_CLAVE() throws NoSuchMethodException {

        if (PROP_CLAVE == null) {
            PROP_CLAVE = JavaBeanStringPropertyBuilder.create().bean(this).name("clave").build();
            GroupBindProperties.add(PROP_CLAVE);
        }
        return PROP_CLAVE;
    }

    public JavaBeanStringProperty getPROP_TIPO() throws NoSuchMethodException {
        if (PROP_TIPO == null) {
            PROP_TIPO = JavaBeanStringPropertyBuilder.create().bean(this).name("tipo").build();
            GroupBindProperties.add(PROP_TIPO);
        }
        return PROP_TIPO;
    }

    public JavaBeanStringProperty getPROP_NOMBRE() throws NoSuchMethodException {

        if (PROP_NOMBRE == null) {
            PROP_NOMBRE = JavaBeanStringPropertyBuilder.create().bean(this).name("nombre").build();
            GroupBindProperties.add(PROP_NOMBRE);
        }
        return PROP_NOMBRE;
    }

    public JavaBeanStringProperty getPROP_APELLIDO() throws NoSuchMethodException {

        if (PROP_APELLIDO == null) {
            PROP_APELLIDO = JavaBeanStringPropertyBuilder.create().bean(this).name("apellido").build();
            GroupBindProperties.add(PROP_APELLIDO);
        }
        return PROP_APELLIDO;
    }

    public JavaBeanIntegerProperty getPROP_NRODOC() throws NoSuchMethodException {

        if (PROP_NRODOC == null) {
            PROP_NRODOC = JavaBeanIntegerPropertyBuilder.create().bean(this).name("nroDoc").build();
            GroupBindProperties.add(PROP_NRODOC);
        }
        return PROP_NRODOC;
    }

    public JavaBeanStringProperty getPROP_TIPODOC() throws NoSuchMethodException {

        if (PROP_TIPODOC == null) {
            PROP_TIPODOC = JavaBeanStringPropertyBuilder.create().bean(this).name("tipoDoc").build();
            GroupBindProperties.add(PROP_TIPODOC);
        }
        return PROP_TIPODOC;
    }

    public void unbindingALL() {
        for (JavaBeanProperty beanBinding : GroupBindProperties) {
            beanBinding.unbind();
        }
    }
}
